 PAG
********************
*       SEG4
********************

]segnum = #$0400  ;current segment number

 ORG $E0C800

*************** MESSAGES *************

* Message for SKIP

MSGSKIP ASC "SKIP"
 DFB CR,EOT

* Message for COMDKEY

MSGKEY DFB CR
 ASC "KEY = "
 DFB EOT

MSGBROUT
 DFB CR
 ASC "OUT OF RANGE"
 DFB BEL,CR,EOT

MSGNOTRM
 DFB CR
 ASC "**ACCESS ERROR**"
 DFB BEL,CR,EOT

MSGHARD DFB CR
 ASC "HARD BREAK"
 DFB CR,EOT

MSGORNG DFB CR
 ASC "OUTSIDE RANGE LIMITS"
 DFB BEL,CR,EOT

MSGNOAC DFB CR
 ASC "NO ACCESS HALT"
 DFB BEL,EOT

* DISPLAY TABLE, FORMAT- ASCII, LOW BYTE OF SWITCH(S) ADDRS

DISPTABL
 DFB "1",$54+$80
 DFB "2",$55+$80
 DFB "4",$0C+$80
 DFB "8",$0D+$80
 DFB "T",$5F,$51+$80
 DFB "A",$0F+$80
 DFB "N",$0E+$80
 DFB "F",$52+$80
 DFB "M",$53+$80
 DFB "L",$56,$50+$80
 DFB "H",$57,$50+$80
 DFB "D",$57,$50,$5E,$0D+$80
 DFB $FF

****************************************
* BANKTABL is used by BANKCHEK subroutine
* to determine which bank the current PC is in.
*
* PATTERN: AABBCC
* AA= Lower limit of PC hi byte
* BB= Pattern to look for in MSTATE
* CC= BIT=0=Don't care
****************************************

 HEX 000000  ;LOWEST LIMIT
BANKTABL   ;MSTATE BIT CONDITION
 HEX 008080  ;7=1
 HEX 024040  ;6=1
 HEX 044042  ;6=1 1=0
 HEX 040606  ;2=1 1=1
 HEX 084040  ;6=1
 HEX 204060  ;6=1 5=0
 HEX 204444  ;6=1 2=1
 HEX 204042  ;6=1 1=0
 HEX 202626  ;5=1 2=1 1=1
 HEX 404040  ;6=1
 HEX C10101  ;0=1
 HEX D08080  ;7=1

**** EFFECTIVE ADDRESS ROUTINES

EFFTABL DA NOEFF-1  ;MODE  $0       #  --  no eff adrs
 DA BANKEFF-1 ;MODE  $1       a  --  calc eff bank only
 DA EFFM2-1  ;MODE  $2      al  --  calc eff bank only
 DA EFFM3-1  ;MODE  $3       d  --  calc eff bank only
 DA NOEFF-1  ;MODE  $4  i or S  --  no eff adrs
 DA EFFM5-1  ;MODE  $5   (d),y
 DA EFFM6-1  ;MODE  $6   [d],y
 DA EFFM7-1  ;MODE  $7   (d,x)
 DA EFFM8-1  ;MODE  $8     d,x
 DA EFFM9-1  ;MODE  $9     d,y
 DA EFFMA-1  ;MODE  $A     a,x
 DA EFFMB-1  ;MODE  $B    al,x
 DA EFFMC-1  ;MODE  $C     a,y
 DA NOEFF-1  ;MODE  $D       r  --  NOT USED
 DA NOEFF-1  ;MODE  $E      rl  --  NOT USED
 DA EFFMF-1  ;MODE  $F     (a)
 DA EFFM10-1 ;MODE $10     [a]
 DA EFFM11-1 ;MODE $11     (d)
 DA EFFM12-1 ;MODE $12     [d]
 DA EFFM13-1 ;MODE $13   (a,x)
 DA EFFM14-1 ;MODE $14     d,s
 DA EFFM15-1 ;MODE $15 (d,s),y
;MODE $16       s
;MODE $17     b,b
;MODE $18       #  --  2 byte only
 ;MODE $19       a  --  (JMP, JSR, PEA)

****************************************
* THIS POINT MUST BE $CA00 OR ABOVE.
****************************************

 ERR *-1/$E0CA00
 DS $E0CA00-*,$FF

*------------------------------*
*  COMDTS
*------------------------------*

COMDTS EQU *
 BEQ ERROR4 ;If no parameter
 JSR TRANSFR4 ;CHECK FOR HEX AND READ
 DFB CHKREADC ;CODE
 BCS ERROR4 ;IF NOT HEX
 STA SUBTRACE ;TO HI BYTE FOR (JUMP) VECTOR
 MEMORY16
 LDA LETTER2 ;HI BYTE & PBR
 STA SUBTRACE+1 ;TO vector
 MEMORY8
 LDA #$80
 STA TSFLAG ;SET FLAG

* continue command in segment0
 PEA LTRACEVC-1 ;address of routine
 PEA S_LTRACE ;segment of routine
 JMP JUMPSEG4 ;transfer segments

******************************
*  COMD> - SKIP NEXT INSTRUCTION
******************************

COMDSKIP
 SEC   ;ADD EXTRA 1
 LDA NUMDISP  ;# BYTES IN CURRENT INST - 1
 ADC PCLO  ;SKIP IT
 STA PCLO
 LDA PCHI
 ADC #0  ;ADD CARRY IF ANY
 STA PCHI

 PEA MSGSKIP  ;location of message
 JSR WRITE4  ;display it

 JSR TRANSFR4 ;DISPLAY NEW LOCATION
 DFB INITDISRC ;code
 LDA #$80
 STA TFLAG  ;RESTORE TRACE MODE
 JMP GETCOM4

******************************
*  COMDKEY - SET KEY
******************************

COMDKEY PEA MSGKEY  ;message location
 JSR WRITE4  ;DISPLAY "KEY = "

 JSR TRANSFR4 ;READ KEYBOARD
 DFB RDCHARC  ;code
 STA KEY  ;SET KEY
 JMP GETCOM4

ERROR4 LDA #BADPAR  ;ERROR NUMBER
 JSR TRANSFR4 ;DO ERROR
 DFB ERRBEEPC ;code
 JMP GETCOM4

******************************
*  COMDSS - SET SWITCH
******************************

COMDSS BEQ ERROR4
 JSR TRANSFR4 ;READ ADDRESS INTO LETTER 1
 DFB CHKREADC ;code
 BCS ERROR4  ;IF NOT VALID
 JSR TRANSFR4 ;RESTORE CURRENT SWITCHES
 DFB RESTTEXTC ;code

* Restore aux ram switches, reset to main ram by SETMSTAT
 JSR RESTAUX

 LDA ALTZP  ;CURRENT ALTZP STATUS
 STA INDYBUF  ;SAVE
* WATCH OUT FOR CX ROM
 LDA LETTER1
 CMP #$06  ;TURN CXROM OFF?
 BEQ :CXOFF  ;IF YES
 CMP #$07  ;TURN CXROM ON?
 BNE :NOTCX  ;IF NO
*CXON
 SEC
 BCS :SETCX
:CXOFF CLC   ;CX OFF
:SETCX ROR CXSTATUS ;SET CX
 JMP :SET  ;CONTINUE

:NOTCX TAX
 STA $C000,X  ;SET SWITCH
 LDA $C000,X  ;NEEDED FOR LANGUAGE CARD SWITCH
 LDA $C000,X  ; ditto

* Sets AUX ram switches to main ram.
:SET JSR TRANSFR4 ;SET MSTATE & CALCULATE BANK
 DFB SETMPBRC ;code
 STA PBR

 JSR TRANSFR4 ;SAVE NEW SWITCHES
 DFB ZPAGSAVEC ;code

 BIT OFFFLAG  ;IS DISPLAY TURNED OFF?
 BMI :NOUPDT  ;IF YES, DON'T UPDATE DISPLAY
 JSR TRANSFR4 ;RESET SCREEN SWITCHES
 DFB SETSCRNC ;code
 JSR TRANSFR4 ;UPDATE DISPLAY
 DFB DISFMESC ;code
 JSR TRANSFR4 ;SET WINDDR
 DFB WINDDRC  ;code
:NOUPDT JMP GETCOM4

*-------------------------
* Restore AUX ram switches. (currently set to main ram)

RESTAUX
 LDA MSTATE
 ASL
 BPL :READM  ;IF SET FOR MAIN RAM
 STA READAUX  ;SET AUX READ
:READM ASL
 BPL :WRITEM  ;IF SET FOR MAIN RAM
 STA WRITAUX  ;SET AUX WRITE
:WRITEM RTS

*----------------------------
* Display "OUT OF RANGE"

DISBROUT
 PEA MSGBROUT ;message location
 JMP DOWRITE4 ;display it

*-------------------------
* Display NOT RAM message

DISNOTRM
 PEA MSGNOTRM ;message location
 JMP DOWRITE4 ;display it

*----------------------
* Display hardware

DISHARD
 PEA MSGHARD  ;message location
 JMP DOWRITE4 ;display it

*----------------------------
OUTPRGR
* If PC is in out slot I/O space then it's OK
 LDA PCHI
 CMP #$C0
 BNE :NOTOK
 LDA SLOTN0
 CLC
 ADC #$8F  ;OUR SLOT I/O LOWER BYTE
 CMP PCLO
 BLT :NOTOK
 SBC #$10
 CMP PCLO
 BLT OKCIS4  ;C=0 IF OK

:NOTOK PEA MSGORNG  ;message location
DOWRITE4
 JSR WRITE4  ;display it
OKCIS4 RTS

NOACMSG PEA MSGNOAC  ;message location
 BRA DOWRITE4 ;display it


*---------------------------------
* Write text to the display device
* The address of the text is on the stack

* THIS ROUTINE MUST BE ABOVE $CF00

WRITE4 STY YBUFF  ;SAVE
 LDY #0
WRITLOP4
 CMP $C800  ;disable DDT RAM
 LDA (3,S),Y  ;get character to display
 CMP $CF00  ;enable DDT RAM
 INY   ;next character
 CMP #EOT  ;finished?
 BEQ WRITDON4 ;if yes
 JSR TRANSFR4 ;display character
 DFB COUTC  ;code
 BRA WRITLOP4 ;loop until done

WRITDON4
 MEMORY16
 PLA   ;get return address
 STA 1,S  ;free parameter space
 MEMORY8
 LDY YBUFF  ;RESTORE
 RTS

*-------------------------------------------------
* Initialize the display window to full screen

WINDFUL LDA #0
 STA WINDLEFT
 STA WINDTOP
 STA CURSHORZ
 LDA #80
 STA WINDWDTH
 LDA #24
 STA WINDBTM
 JSR TRANSFR4 ;SET BASL & CLEAR HOME
 DFB CLRHOMEC ;CODE

 SEC
 ROR WINDFLG  ;indicate windows are off

 RTS

******************************
* COMDSD - SET DISPLAY SWITCH
******************************

COMDSD BEQ :SDERR  ;IF NO CHAR FOLLOWS

* Set the display switches
* ACC contains command letter

 CMP #"S"  ;Super Hi-Res ?
 BNE :NOSUP  ;if no
 LDA INVISIBL ;INVISIBLE MODE FLAG
 PHA   ;SAVE
 JSR USERDISP ;Restore User's Display
 LDA #$80  ;Set Super Hi-Res bit
 TSB SUPERHR
 LDA #$08  ;Enable shadowing of Super Hi-Res
 TRB SHADOW  ;Store
 BRA :SAVENEW ;Save the new display switches

:NOSUP LDX #0
 STA SELFMOD  ;SAVE COMMAND LETTER
 STA $C800  ;SELECT EXT ROM
 LDA DISPTABL,X ;GET COMMAND LETTER FROM TABLE
 STA $CF00  ;SELECT EXT RAM
:LOOK CMP SELFMOD  ;IS IT THIS COMMAND
 BEQ :MATCH  ;IF YES
 STA $C800  ;SELECT EXT ROM
:LOOP INX
 LDA DISPTABL,X ;GO TO NEXT COMMAND LETTER
 BPL :LOOP
 INX
 LDA DISPTABL,X
 STA $CF00  ;SELECT EXT RAM
 CMP #$FF  ;END OF TABLE ?
 BNE :LOOK  ;IF NO

:SDERR JMP ERROR4  ;INDICATE ERROR & GOTO GETCOM4


:MATCH STX SELFMOD+1 ;SAVE
 LDA INVISIBL ;INVISIBLE MODE FLAG
 PHA   ;SAVE
 JSR USERDISP ;Restore User's display
 LDX SELFMOD+1 ;RESTORE

 LDA SELFMOD
 CMP #"T"  ;Text mode ?
 BNE :NOTXT  ;If no
 LDA #$80
 TRB SUPERHR  ;Turn off Super Hi-Res if enabled

* Initialize self modifing code

:NOTXT LDA #$8D  ;STA abs OPCODE
 STA SELFMOD
 LDA #$C0  ;HI BYTE OF SWITCH ADDRESS
 STA SELFMOD+2
 LDA #$60  ;RTS OPCODE
 STA SELFMOD+3

* Set the selected switches

:NEXTS STA $C800  ;SELECT EXT ROM
 INX
 LDA DISPTABL,X ;LOW BYTE OF SWITCH
 STA $CF00  ;SELECT EXT RAM
 PHP   ;SAVE N FLAG
 AND #$7F  ;STRIP BIT 7
 STA SELFMOD+1 ;PUT IN ROUTINE
 JSR SELFMOD  ;SET SWITCH
 PLP   ;WAS IT LAST SWITCH
 BPL :NEXTS  ;IF NO

* Save the new display settings

:SAVENEW
 JSR TRANSFR4 ;set MSTATE (sets aux switches) calculate bank
 DFB SETMPBRC ;code
 JSR TRANSFR4 ;SAVE NEW DISPLAY SWITCHES
 DFB SAVEDISPC ;code
 PLA   ;GET INVISIBL MODE FLAG
 STA INVISIBL ;RESTORE
 JMP GETCOM4

*------------------------------------
* Restore the user's display settings

USERDISP

* Turn DDT display off
 JSR TRANSFR4 ;RESTORE TEXT & DISPLAY SWITCHES
 DFB RESTTEXTC ;code
 LDA #$80
 STA OFFFLAG  ;TURN OFF EXT DISPLAY

 LDA #0
 STA INVISIBL ;CLEAR IF SET
 JSR TRANSFR4 ;RESTORE DISPLAY SWITCHES
 DFB RESTDISPC ;code
 JMP RESTAUX  ;restore aux ram switches & RTS

******************************
* COMDPW - PROTECTION WINDOW
******************************

COMDPW LDX #5*6  ;0-5 BUFFFERS 6 BYTES EACH BUFFER
 STX LETTER1  ;SAVE
 JSR TRANSFR4 ;DISPLAY PROT WINDOW
 DFB DISPROTWC ;code
 JSR TRANSFR4 ;HOME
 DFB HOMEC  ;code
 LDA #$A0  ;SPACE
 STA PROMPT
PWINPUT LDA IOMODE  ;ARE WE IN SERIAL or printer MODE ?
 BEQ :NOSER  ;IF NOT

* Display current PW info if serial or printer
 LDX LETTER1
 LDA PROTADR,X ;GET PROTECTION TYPE
 JSR TRANSFR4 ;DISPLAY
 DFB COUTC  ;code
 LDA PROTADR+1,X
 JSR TRANSFR4 ;PRINT BYTE
 DFB PRBYTEC  ;code
 LDA #"/"
 JSR TRANSFR4
 DFB COUTC
 LDA PROTADR+2,X
 JSR TRANSFR4
 DFB PRBYTEC  ;code
 LDA PROTADR+3,X
 JSR TRANSFR4
 DFB PRBYTEC  ;code
 LDA #"."
 JSR TRANSFR4
 DFB COUTC  ;code
 LDA PROTADR+4,X
 JSR TRANSFR4
 DFB PRBYTEC  ;code
 LDA PROTADR+5,X
 JSR TRANSFR4
 DFB PRBYTEC  ;code	
 LDA #" "
 JSR TRANSFR4
 DFB COUTC  ;code

:NOSER JSR TRANSFR4 ;GET LINE
 DFB GETLNC  ;code
 BCS :END  ;if <esc> key pressed
 INX
 STX TEMP  ;IN POINTER
 LDY #0
 JSR GETCHAR  ;GET FROM IN,Y
 BEQ :CR  ;IF <CR>
 CMP #"T"  ;TRACE RANGE ?
 BEQ :SAVETYPE ;IF YES
 CMP #"P"  ;PROGRAM ONLY RANGE ?
 BEQ :SAVETYPE ;IF YES
 CMP #"N"  ;NO ACCESS RANGE ?
 BEQ :SAVETYPE ;IF YES
 CMP #$A0  ;SPACE MEANS REMOVE TYPE
 BNE :ERROR  ;IF NO
:SAVETYPE
 LDX LETTER1  ;PROTADR POINTER
 STA PROTADR,X ;SAVE TYPE

* Load in 1 byte of PROTADR address, loop until done
:PRBYT INX   ;NEXT BYTE
 JSR GETCHAR  ;READ IN,Y
 BEQ :CR  ;IF <CR>
 JSR CHKHEX  ;CONVERT TO HEX
 BCS :ERROR  ;IF NOT HEX
 JSR MSNYBPW  ;UPDATE MS NYBBLE OF DATA
 JSR GETCHAR  ;READ IN,Y
 BEQ :CR
 JSR CHKHEX
 BCS :ERROR
 JSR LSNYBPW  ;UPDATE LS NYBBLE OF DATA
 CPY #3  ;SKIP "/" ?
 BEQ :SKIP  ;IF YES
 CPY #8  ;SKIP "." ?
 BNE :PRBYT
:SKIP JSR GETCHAR
 BEQ :CR
 BNE :PRBYT
:ERROR JSR TRANSFR4 ;RING BELL
 DFB BELLC  ;code
:CR LDA CURSVERT ;SAVE CURRENT POSITION
 PHA
 JSR TRANSFR4 ;UPDATE PROT WINDOW
 DFB DISPROTWC ;code
 PLA
 STA CURSVERT ;RESTORE POSITION
 LDA #0
 STA CURSHORZ ;LEFT EDGE
 JSR TRANSFR4 ;RESTORE BAS
 DFB VTABC  ;code
 LDX LETTER1  ;PROTADR POINTER
 BNE :NEXT  ;if not at bottom of window
 JMP COMDPW  ;go to top of window
:NEXT SEC
 TXA
 SBC #6  ;GOTO NEXT LOCATION
 STA LETTER1
 JMP PWINPUT  ;LOOP

* Set proper flags & leave
:END LDA #0
 STA REALTIME ;CLEAR ALL FLAGS
 STA PROGONLY
 STA NOACCESS
 LDX #6*5
:SETFLG LDA PROTADR,X ;GET TYPE
 CMP #"T"
 BNE :CHKP
 STA REALTIME ;SET FLAG
:CHKP CMP #"P"
 BNE :CHKN
 STA PROGONLY ;SET FLAG
:CHKN CMP #"N"
 BNE :NEXTTYP
 STA NOACCESS ;SET FLAG
:NEXTTYP
 TXA
 BEQ :LEAVE
 SEC
 SBC #6  ;NEXT TYPE
 TAX
 BCS :SETFLG  ;<ALWAYS>

:LEAVE JSR TRANSFR4 ;UPDATE PROT WINDOW
 DFB DISPROTWC ;code
 JSR TRANSFR4 ;SET DR WINDOW
 DFB WINDDRC  ;code

 JMP GETCOM4

* Update the MS nybble of data byte

MSNYBPW ASL
 ASL
 ASL
 ASL
 PHA   ;SAVE DIGIT
 LDA #$0F
 BNE STRIP

* Update the LS nybble of data byte

LSNYBPW PHA   ;SAVE DIGIT
 LDA #$F0
STRIP AND PROTADR,X ;STRIP DIGIT
 STA PROTADR,X
 PLA   ;GET NEW DIGIT
 ORA PROTADR,X
 STA PROTADR,X ;PUT IN
 RTS

* Convert ACC to hex

CHKHEX CMP #$B0
 BLT :NOTHEX
 CMP #$BA
 BLT :OK
 CMP #$C0
 BLT :NOTHEX
 CMP #$C7
 BLT :OKAF
:NOTHEX SEC   ;SET NOT HEX FLAG
 RTS

:OKAF CLC
 ADC #9  ;CONVERT TO $A - $F
:OK AND #$0F  ;STRIP HI DIGIT
 CLC   ;SET HEX FLAG
 RTS

GETCHAR LDA IN,Y ;READ CHAR
 INY
 DEC TEMP ;IN POINTER
 RTS

******************************
* COMDMW - MEMORY WINDOW
******************************

COMDMW JSR TRANSFR4 ;SET MEM WINDOW
 DFB DISMEMWC ;code
 JSR TRANSFR4 ;HOME W/NO CLEAR
 DFB HOMEC  ;code

* Set window width to froce return at end of address
 LDA #8
 STA WINDWDTH
 LDX #11*3  ;0-11 BUFFFERS 3 BYTES EACH BUFFER
 STX LETTER1  ;SAVE

 LDA #$80  ;NULL
 STA PROMPT
MWINPUT JSR TRANSFR4 ;GET LINE
 DFB GETLNC  ;code
 BCS :END  ;if <esc> key pressed
 INX
 STX TEMP  ;IN POINTER
 LDY #0

 LDX LETTER1  ;MEM ADDRESS POINTER
 DEX

* Load in 1 byte of MEMADR address, loop until done
:PRBYT INX   ;NEXT BYTE
 JSR GETCHAR  ;READ IN,Y
 BEQ :CR  ;IF <CR>
 JSR CHKHEX  ;CONVERT TO HEX
 BCS :ERROR  ;IF NOT HEX
 JSR ASLUPMW  ;UPDATE MS NYBBLE OF DATA
 JSR GETCHAR  ;READ IN,Y
 BEQ :CR
 JSR CHKHEX
 BCS :ERROR
 JSR UPDTMW  ;UPDATE LS NYBBLE OF DATA
 CPY #2  ;SKIP "/" ?
 BNE :PRBYT  ;IF NO
:SKIP JSR GETCHAR
 BEQ :CR
 BNE :PRBYT  ;<ALWAYS>
:ERROR JSR TRANSFR4 ;RING BELL
 DFB BELLC  ;code
:CR LDA CURSVERT ;SAVE CURRENT POSITION
 PHA
 JSR TRANSFR4 ;UPDATE PROT WINDOW
 DFB DISMEMWC ;code
 LDA #8
 STA WINDWDTH ;RESET WINDOW WIDTH
 PLA
 STA CURSVERT ;RESTORE POSITION
 LDA #0
 STA CURSHORZ ;LEFT EDGE
 JSR TRANSFR4 ;RESTORE BAS
 DFB VTABC  ;code
 LDX LETTER1  ;MEMADR POINTER
 BNE :NEXT  ;if not bottom of window
 JMP COMDMW  ;go to top of window
:NEXT SEC
 TXA
 SBC #3  ;GOTO NEXT LOCATION
 STA LETTER1
 JMP MWINPUT  ;LOOP

:END JSR TRANSFR4 ;UPDATE MW DISPLAY
 DFB DISMEMWC ;code
 JSR TRANSFR4 ;SET DR WINDOW
 DFB WINDDRC ;code

 JMP GETCOM4

* Update hi nybble of MEMWADR

ASLUPMW ASL
 ASL
 ASL
 ASL
 PHA   ;SAVE DIGIT
 LDA #$0F
 BNE STRIPMW

* Update low nybble of MEMWADR

UPDTMW PHA   ;SAVE DIGIT
 LDA #$F0
STRIPMW AND MEMWADR,X ;STRIP DIGIT
 STA MEMWADR,X
 PLA   ;GET NEW DIGIT
 ORA MEMWADR,X
 STA MEMWADR,X ;PUT IN
 RTS


****************************************
* Calculate the bank for the current MEMLOW & MEMHI location
*
* Location MSTATE contains the memory state byte. Use this to
* determine if current MEMLOW & MEMHI location is in main or
* aux memory. Modify MSTATE byte for this test, make BIT5=HIRES
*****************************************

BANKCHEK LDA HIRESFLG
 AND #$80
 LSR
 LSR   ;PUT IN BIT 5
 EOR MSTATE
 AND #$20
 EOR MSTATE  ;BIT5 = HIRES
 STA TEMP
 LDX #$21
 LDA MEMHI  ;HI BYTE OF PC
 CMP #$C0
 BEQ MAINRAM
MATCHPC LDA MEMHI  ;HI BYTE OF PC
 CMP $C800
 CMP BANKTABL,X
 STA $CF00
 BLT NOTAUX  ;TRY NEXT LIMIT

 LDA TEMP  ;GET MSTATE WITH MOD. BIT 5
 CMP $C800  ;DISABLE DDT RAM
 EOR BANKTABL+1,X ;XOR WITH TEST BYTE
 AND BANKTABL+2,X ;AND WITH TEST BYTE
 BEQ ISAUX  ;IF =0 THEN AUX RAM

* IF NOT AUX RAM, SHOULD WE USE THE NEXT BANKTABL FLAGS
 LDA BANKTABL-3,X ;GET NEXT BANKTABL LOWER LIMIT
 CMP BANKTABL,X ;SAME AS CURRENT LIMIT ?
 STA $CF00  ;ENAB EXT RAM
 BNE MAINRAM  ;IF NO

NOTAUX DEX
 DEX
 DEX
 BPL MATCHPC
MAINRAM
 LDA DBR
 BRA BANKSET

* IF AUX RAM
ISAUX STA $CF00  ;ENABLE EXT RAM
 LDA DBR
 CMP #2  ;BANK IS 1 ONLY IF DBR IS 00 OR 01
 BGE BANKSET
 LDA #01
BANKSET RTS   ;LEAVE

*----------------------------------------
* Calculate bank # of effective address
* EFFADRS+2, +1, +0 = effective PBR, hi, low respectively

BANKEFF MX8
 PHX
 PHP   ;SAVE CARRY
 LDA MEMHI  ;SAVE MEMHI
 PHA
 LDA EFFADRS+1 ;GET HI BYTE OF EFF ADRS
 STA MEMHI  ;SET UP MEMHI FOR BANKCHEK
 JSR BANKCHEK ;CALCULATE BANK #
 STA EFFADRS+2 ;SAVE BANK # OF EFFADRS
 PLA
 STA MEMHI  ;RESTORE MEMHI
 PLP   ;RESTORE CARRY
 PLX
 RTS

*-------------------------------------------------
* Calculate the effective address of current instruction

CALCEFF LDX MODE  ;GET MODE * 2
 MEMORY16
 CMP $C800  ;SELECT EXT ROM
 LDA EFFTABL,X ;GET ADDRESS OF PROPER ROUTINE
 CMP $CF00  ;SELECT EXT RAM
 PHA   ;PUT ON STACK
 CLC
 RTS   ;GOTO ROUTINE WITH RTS
 MX %11

 MX %01
NOEFF MEMORY8
 RTS

* Calculate effective address routines

* MODE 7 (d,X)

 MX %01
EFFM7 LDA XREG  ;USER'S X
 ADC EFFADRS  ;ADD X TO OPERAND
M11CONT JSR LDA_DREG ;+ DREG, lda (operand) from bank 0
 STA EFFADRS
 BRA BANKEFF
 MX %11

* MODE 11  (d)

 MX %01
EFFM11 LDA EFFADRS  ;GET OPERAND
 BRA M11CONT
 MX %11

* MODE B  al,X

 MX %01
EFFMB LDA EFFADRS
 ADC XREG
 STA EFFADRS

* MODE 2 al

EFFM2 MEMORY8
 LDA EFFADRS+2
 BRA ADCBALT

* MODE 14  d,S

 MX %01
EFFM14 LDA STACK  ;LOW BYTE STACK
 BRA M14CONT
 MX %11

* MODE 15  (d,S),Y

 MX %01
EFFM15 LDA STACK
 ADC EFFADRS
 BRA M15CONT
 MX %11

* MODE 5  (d),Y

 MX %01
EFFM5 LDA EFFADRS  ;GET OPERAND
 ADC DREG
M15CONT JSR LDA_OPR0 ;LDA (OPERAND) from bank 0
 CLC
 ADC YREG  ;USER'S Y

EFFSTA STA EFFADRS
 MEMORY8
 LDA DBR
 ADC #0
 BRA BANKALT

* MODE 6  [d],Y

 MX %01
EFFM6 JSR LDA_EFF  ;lda operand, + DREG, lda (operand) bank 0
 CLC
 ADC YREG
 STA EFFADRS
 MEMORY8
 INY
 PHP   ;SAVE CARRY
 JSR LDA_BNK0 ;get PBR of [d] from bank 0
EFFADC2 PLP   ;RESTORE CARRY
ADCBALT ADC #0

* Enter with ACC = effective bank# to use
BANKALT MX8
 LDX DBR
 PHX   ;SAVE DBR
 STA DBR  ;GET EFF. ADDRESS FOR BANK 0
 JSR BANKEFF
 PLX
 STX DBR  ;RESTORE DBR
 RTS

* MODE 3  d

 MX %01
EFFM3 LDA #0
 BRA M9CONT
 MX %11

* MODE 8  d,X

 MX %01
EFFM8 LDA XREG  ;USERS X
M9CONT ADC DREG
M14CONT ADC EFFADRS  ;ADD X TO OPERAND
 STA EFFADRS
 LDA #0000
 BRA BANKALT  ;CALC BANK # & RTS
 MX %11

* MODE 9  d,Y

 MX %01
EFFM9 LDA YREG  ;USERS Y
 BRA M9CONT
 MX %11

* MODE C  a,Y

 MX %01
EFFMC LDA YREG  ;USERS Y
 BRA MCCONT
 MX %11

* MODE F  (a)

 MX %01
EFFMF LDA EFFADRS  ;GET OPERAND
M13CONT JSR LDAOPER  ;LDA (OPERAND)
 STA EFFADRS
 LDA PBR
 BRA BANKALT
 MX %11

* MODE $10 [a]

 MX %01
EFFM10 LDA EFFADRS  ;GET OPERAND
 JSR LDAOPER  ;LDA (OPERAND)
 STA EFFADRS
 MEMORY8
M12CONT INY
 JSR LDA_BNK0 ;get byte from bank 0
 BRA BANKALT

* MODE A  a,X

 MX %01
EFFMA LDA XREG  ;USERS X
MCCONT ADC EFFADRS  ;LOW BYTE
 BRA EFFSTA
 MX %11

* MODE 12  [d]

 MX %01
EFFM12 JSR EFFM11
 BRA M12CONT
 MX %11

* MODE 13  (a,X)

 MX %01
EFFM13 LDA XREG  ;USERS X REG
 ADC EFFADRS  ;ADD TO OPERAND
 BRA M13CONT
 MX %11

* LDA (OPERAND)

 MX %01
LDA_EFF LDA EFFADRS  ;get operand
LDA_DREG
 ADC DREG  ;add direct register
LDA_OPR0
 LDY #0
 STY DBRDDT  ;use bank 0
LDAOPER PHP   ;save carry & MX
 STA LOWADD
 LDY #0
 MEMORY8
 JSR TRANSFR4 ;get hi byte
 DFB LDAINDYC ;code
 PHA   ;save hi byte
 INY   ;next byte
 JSR TRANSFR4 ;get low byte
 DFB LDAINDYC
 XBA   ;low/hi form
 LDA MEMPBR
 STA DBRDDT  ;restore to program bank
 PLA   ;restore hi byte
 PLP   ;restore carry & MX
 RTS
 MX %11

* Get byte from bank 0
LDA_BNK0
 STZ DBRDDT  ;get from bank 0
 JSR TRANSFR4 ;
 DFB LDAINDYC ;code
 PHA   ;save
 LDA MEMPBR
 STA DBRDDT  ;restore to program bank
 PLA   ;restore
 RTS

*----------------------------------------
*  GETCOM4 - do <CR> & get user command

GETCOM4 PEA GETCOMCR-1 ;address of command
 PEA S_GETCOM ;segment of command
 JMP JUMPSEG4 ;goto command

*----------------------------------------
***** THIS SEGMENTS GLOBAL SUBROUTINES *****

SUBTABL4

DISBROUTC EQU *-SUBTABL4*4+4+$100
 DA DISBROUT-1

DISNOTRMC EQU *-SUBTABL4*4+4+$100
 DA DISNOTRM-1

DISHARDC EQU *-SUBTABL4*4+4+$100
 DA DISHARD-1

OUTPRGRC EQU *-SUBTABL4*4+4+$100
 DA OUTPRGR-1

NOACMSGC EQU *-SUBTABL4*4+4+$100
 DA NOACMSG-1

WINDFULC EQU *-SUBTABL4*4+4+$100
 DA WINDFUL-1

BANKCHEKC EQU *-SUBTABL4*4+4+$100
 DA BANKCHEK-1

CALCEFFC EQU *-SUBTABL4*4+4+$100
 DA CALCEFF-1

*****************************************
*  SEGMENT CROSSOVER AREA  *
*****************************************

 LST ON
S4END = $E0CF91-*
 do nolist
 LST OFF
 fin
 ERR *-1/$E0CF91
 DS $E0CF91-*,$FF

******** SAVE THE ACC, X, Y AND P REGISTERS *******
* Returns with MX = 11, saves registers

SAVEAXP4
 PHP   ;SAVE STATUS
 MX16
 STX XSAVESEG ;save 16 bits
 STY YSAVESEG ;save 16 bits
 STA ASAVESEG ;save 16 bits
 MX8
 PLA   ;GET STATUS
 STA PSAVESEG ;SAVE
 RTS

****** RESTORE THE ACC, X, Y AND P REGISTERS ******
* restores registers

RESTAXP4
 MEMORY8
 LDA PSAVESEG
 PHA
 MX16
 LDX XSAVESEG
 LDY YSAVESEG
 LDA ASAVESEG
 PLP
 RTS
 MX %11

*----------------------------------------
* Do a direct transfer to other segments

JUMPSEG4
 JSR SAVEAXP4
 LDY SLOTN0
 PLA   ;pull junk byte from dest. seg
 PLA   ;get destination segment
 STA SEGMBASE,Y ;the next inst' will be in new seg
 JSR RESTAXP4 ;restore after xfer from other seg
 RTS   ;pull destination address from stack

* TRANSFER TO OTHER SEGMENTS

TRANSFR4

 JSR SAVEAXP4
 MEMORY16
 PLA   ;get return address from stack
 INC   ;inc to point at code byte & for RTS
 PHA
 MEMORY8
 LDA #4  ;CURRENT SEG #
 PHA
 LDY #0
 LDA (2,S),Y  ;GET CODE BYTE
 PHA   ;SAVE CODE
 AND #$07  ;STRIP ALL BUT SEG #
 LDY SLOTN0
 STA SEGMBASE,Y ;NEXT INSTR. RUN FROM NEW SEGMENT
* NEW SEGMENT
 PLA   ;GET CODE
 PEA RETURN4  ;where to return to
 AND #$F8  ;STIP OFF SEG# LEAVING SUB #
 LSR
 LSR   ;LEAVE SUB# MULTIPLIED BY 2
* GET ADDRESS OF SUB FROM SUBTABL & PUSH ON STACK
 TAY
 MEMORY16
 LDA SUBTABL4,Y
 PHA
 BRA RESTAXP4 ;RESTORE REGISTERS, RTS TO SUBROUTINE
 MX %11

* RETURN HERE FROM SUBROUTINE

RETURN4 EQU *-1
 JSR SAVEAXP4
 PLA   ;SEG # TO RETURN TO
 LDY SLOTN0
 STA SEGMBASE,Y ;RETURN TO SEGMENT
 BRA RESTAXP4

 DS \,$FF  ;PUT OBJECT AT NEXT PAGE
